/**
 *
 */
package hichecker.ui.custom_views.conflict_handling;

import hichecker.controller.Config;
import hichecker.controller.MainController;
import hichecker.ui.components.custom_table.CustomTable;
import hichecker.ui.components.icon_factory.IconFactory;
import hichecker.ui.components.icon_factory.IconFactory.IconType;
import hichecker.ui.general_views.container_panel.content.ContentPanel;
import hichecker.university.Course;
import hichecker.university.ImportExportCourse;
import hichecker.university.Series;
import hichecker.university.Student;
import hichecker.university.StudentComparator;
import hichecker.university.Task;
import hichecker.university.StudentComparator.CompareValue;

import java.awt.Adjustable;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.SortOrder;
import javax.swing.table.JTableHeader;

/**
 * JPanel showing the differences between the opened file and an imported series. Enables conflict
 * resolution.
 */
public class ConflictView extends ContentPanel {

	private ConflictImportedTableModel modelImported;
	private List<Student> allStudents;
	private Course openedCourse;
	private ImportExportCourse importedCourse;
	private Series openedSeries;
	private Series importedSeries;

	private static JScrollPane leftPane;
	private static JScrollPane rightPane;
	private static CustomTable tblOpened;
	private static CustomTable tblImported;

	private static SortOrder order;
	private int formerColumn;

	private MainController controller;

	/**
	 * Creates the view
	 *
	 * @param importedCourse
	 *            imported course with all information
	 * @param allStudents
	 *            list of all students, containing all old students and all new students
	 * @param controller
	 *            the classic {@link MainController}
	 */
	public ConflictView(ImportExportCourse importedCourse, MainController controller) {
		super(importedCourse);
		this.controller = controller;

		// Get the original and new values
		this.importedCourse = importedCourse;
		importedSeries = importedCourse.getTheOnlySeries();

		openedCourse = controller.getCourse();
		openedSeries = openedCourse.getSeriesByID(importedSeries.getID());

		allStudents = new ArrayList<Student>();
		// Add all opened students
		for (Student student : openedCourse.getParticipants())
			allStudents.add(student);

		// Add all imported students if not already done
		for (Student student : importedCourse.getParticipants())
			if (!allStudents.contains(student))
				allStudents.add(student);
		Collections.sort(allStudents, new StudentComparator(CompareValue.LASTNAME, SortOrder.ASCENDING));

		// Table for the opened values
		ConflictOpenedTableModel modelOpened = new ConflictOpenedTableModel(openedCourse.getParticipants(), openedSeries, allStudents);
		tblOpened = new CustomTable(modelOpened);
		leftPane = new JScrollPane(tblOpened);

		// Table for the imported values
		modelImported = new ConflictImportedTableModel(openedCourse, importedCourse, allStudents);
		tblImported = new CustomTable(modelImported);
		rightPane = new JScrollPane(tblImported);

		// Scrollbarlistener that handels scrolling ob boths panes at once
		TwoBarAdjustmentListener lis = new TwoBarAdjustmentListener();
		leftPane.getHorizontalScrollBar().addAdjustmentListener(lis);
		rightPane.getHorizontalScrollBar().addAdjustmentListener(lis);
		leftPane.getVerticalScrollBar().addAdjustmentListener(lis);
		rightPane.getVerticalScrollBar().addAdjustmentListener(lis);

		// Button to confirm changes
		JButton btnConfirm = IconFactory.getIconButton(Config.BUTTON_CONFIRM, null,
				IconType.OK, new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent e) {
				confirmChanges();
			}
		});

		// Layout of the content
		GroupLayout layout = new GroupLayout(this);
		setLayout(layout);

		layout.setAutoCreateGaps(true);
		layout.setAutoCreateContainerGaps(true);

		// Horizontal Layout
		layout.setHorizontalGroup(layout.createSequentialGroup()
			.addGroup(layout.createParallelGroup()
				.addComponent(leftPane)
				.addComponent(btnConfirm)
			)
			.addComponent(rightPane)
		);

		// Vertical Layout
		layout.setVerticalGroup(layout.createSequentialGroup()
			.addGroup(layout.createParallelGroup()
				.addComponent(leftPane)
				.addComponent(rightPane)
			)
			.addComponent(btnConfirm)
		);
		setVisible(true);

		tblOpened.setRowSorter(null);
		tblOpened.getTableHeader().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				sortTableView(e);
			}
		});

		tblImported.setRowSorter(null);
		tblImported.getTableHeader().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				sortTableView(e);
			}
		});
	}

	private void sortTableView(MouseEvent e) {
		JTableHeader header = (JTableHeader) e.getSource();
		int column = header.getColumnModel().getColumnIndexAtX(e.getX());
		if (header.getTable().getModel() instanceof ConflictImportedTableModel) {
			column -= 1;
		}

		if (column == formerColumn)
			toggleSortOrder();
		else {
			formerColumn = column;
			order = SortOrder.ASCENDING;
		}

		switch (column) {
		case 0:
			Collections.sort(allStudents, new StudentComparator(CompareValue.LASTNAME, order));
			break;
		case 1:
			Collections.sort(allStudents, new StudentComparator(CompareValue.FIRSTNAME, order));
			break;
		case 2:
			Collections.sort(allStudents, new StudentComparator(CompareValue.MATRIKEL, order));
			break;
		case 3:
			Collections.sort(allStudents, new StudentComparator(CompareValue.STUDYCOURSE, order));
			break;
		default: return;
		}
		updateTables();
	}

	private void toggleSortOrder() {
		if (order == SortOrder.ASCENDING)
			order = SortOrder.DESCENDING;
		else
			order = SortOrder.ASCENDING;
	}

	private void updateTables() {
		tblImported.repaint();
		tblOpened.repaint();
	}

	/**
	 * Commits all changes
	 */
	private void confirmChanges() {
		for (Student student : allStudents) {
			// Don't save changes
			if (!modelImported.changesConfirmed(student))
				continue;

			// Get the two different students
			Student oldStudent = openedCourse.hasParticipant(student);
			Student newStudent = importedCourse.hasParticipant(student);

			// Can't make changes, so skip it
			if (newStudent == null)
				continue;

			// The student is new, so add him
			if (oldStudent == null) {
				openedCourse.getParticipants().add(newStudent);
				oldStudent = newStudent;
			}

			// Set the student's new values
			oldStudent.takeOverValues(newStudent);

			// For each task copy the gained points
			for (Task task : importedSeries.getTasks()) {
				Task oldTask = openedSeries.getTaskByID(task.getID());
				oldTask.setGainedPoints(oldStudent,task.getGainedPoints(newStudent));
			}
		}

		// Close the import
		controller.closeImportFile(importedCourse);
	}


	/**
	 * Changes the scrollbar position of both scrollpanes present in this view
	 * @param value
	 * @param orientation
	 */
	public static void changeScrollbarValues(int value, int orientation) {
		if (orientation == Adjustable.HORIZONTAL) {
			rightPane.getHorizontalScrollBar().setValue(value);
			leftPane.getHorizontalScrollBar().setValue(value);
		} else {
			rightPane.getVerticalScrollBar().setValue(value);
			leftPane.getVerticalScrollBar().setValue(value);
		}
	}

	/**
	 * A AdjustmentListener that calls {@link ConflictView#changeScrollbarValues(int, int)}, so all
	 * scrollpanes in this view change at the same time
	 */
	private class TwoBarAdjustmentListener implements AdjustmentListener {
		@Override
		public void adjustmentValueChanged(AdjustmentEvent evt) {
			ConflictView.changeScrollbarValues(evt.getValue(), evt.getAdjustable().getOrientation());
		}
	}

	@Override
	public ContentPanel switchViewSettings() {
		return this;
	}
}